import cn.hutool.core.io.FileUtil;

import java.io.File;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 生成 FileSignatureUtil
 *
 * @author WeiHongBin
 */
public class GenerateFileSignatureUtil {
    private static final Map<String, byte[][]> FILE_SIGNATURE_MAP = new HashMap<>();

    public static void main(String[] args) {
        final List<String> strings = FileUtil.readLines(new File("FileSignatureDatabase.md"), StandardCharsets.UTF_8);
        // 删除表头
        strings.remove(0);
        strings.remove(0);
        StringBuilder sb = new StringBuilder();
        sb
                .append("import java.io.File;\n")
                .append("import java.io.FileInputStream;\n")
                .append("import java.io.IOException;\n")
                .append("import java.util.Arrays;\n")
                .append("import java.util.HashMap;\n")
                .append("import java.util.Map;\n")
                .append("import java.util.Objects;\n\n")
                .append("public class FileSignatureUtil {\n")
                .append("    private static final Map<String, byte[][]> FILE_SIGNATURE_MAP = new HashMap<>();\n\n")
                .append("    static {\n");

        StringBuilder contentSb = new StringBuilder();
        String preKey = "";
        String preComment = "";
        for (int i = 0; i < strings.size(); i++) {
            final String[] cols = strings.get(i).split("\\|");
            final String key = cols[1].trim();
            // Java 变量命名不可以 包含 * .
            String comment = "*".equals(key) ? "extAsterisk" : "ext" + key;
            comment = comment.replace(".", "point");

            if (FILE_SIGNATURE_MAP.containsKey(key)) {
                sb.append(',');
                contentSb.append(',');
            } else {
                if (i != 0) {
                    sb.append("]\n");
                    contentSb.append("};\n");
                    contentSb.append("\t\tFILE_SIGNATURE_MAP.put(\"").append(preKey).append("\", ").append(preComment).append(");\n");
                    sb.append(contentSb);
                    contentSb = new StringBuilder();
                }
                preComment = comment;
                preKey = key;

                contentSb.append("\t\tbyte[][] ").append(comment).append(" = {");
                sb.append("\t\t// ").append(key).append(" [");
            }
            String bytesStr = cols[2].trim();
            final String[] s3 = bytesStr.split(" ");
            StringBuilder newBytesStr = new StringBuilder();
            for (int i1 = 0; i1 < s3.length; i1++) {
                final String byteStr = s3[i1];
                // 需要强转
                if (Integer.parseInt(byteStr, 16) > Byte.MAX_VALUE) {
                    newBytesStr.append("(byte) ");
                }
                newBytesStr.append("0x").append(byteStr);
                if (i1 + 1 != s3.length) {
                    newBytesStr.append(", ");
                }
            }
            contentSb.append("{").append(newBytesStr).append("}");
            sb.append("'").append(cols[3].trim()).append("'");
            FILE_SIGNATURE_MAP.put(key, null);
        }
        sb.append("]\n");
        contentSb.append("};\n");
        contentSb.append("\t\tFILE_SIGNATURE_MAP.put(\"").append(preKey).append("\", ").append(preComment).append(");\n");
        sb.append(contentSb);
        sb.append("    }\n");
        sb.append("\t/**\n" +
                "\t * 文件头检查\n" +
                "\t *\n" +
                "\t * @param file 文件\n" +
                "\t * @return 0 不符合 1 符合 -1 未找到\n" +
                "\t */\n" +
                "\tpublic static int check(File file) throws IOException {\n" +
                "\t\tfinal String fileName = file.getName().toUpperCase();\n" +
                "\t\tfinal int i = fileName.lastIndexOf(\".\");\n" +
                "\t\tString suffix = i == -1 ? fileName : fileName.substring(i + 1);\n" +
                "\t\tbyte[][] fileSignatureBytes = FILE_SIGNATURE_MAP.get(suffix);\n" +
                "\t\tif (Objects.isNull(fileSignatureBytes)) {\n" +
                "\t\t\tString extTARpointZ = \"TAR.Z\";\n" +
                "\t\t\tif (fileName.endsWith(extTARpointZ)) {\n" +
                "\t\t\t\tfileSignatureBytes = FILE_SIGNATURE_MAP.get(extTARpointZ);\n" +
                "\t\t\t}\n" +
                "\t\t}\n" +
                "\t\tif (Objects.isNull(fileSignatureBytes)) {\n" +
                "\t\t\treturn -1;\n" +
                "\t\t}\n" +
                "\t\tfor (byte[] sigBytes : fileSignatureBytes) {\n" +
                "\t\t\tfinal int length = sigBytes.length;\n" +
                "\t\t\tfinal byte[] fileBytes;\n" +
                "\t\t\ttry (FileInputStream fileInputStream = new FileInputStream(file)) {\n" +
                "\t\t\t\tfileBytes = new byte[length];\n" +
                "\t\t\t\tfileInputStream.read(fileBytes);\n" +
                "\t\t\t}\n" +
                "\t\t\tif (Arrays.equals(fileBytes, sigBytes)) {\n" +
                "\t\t\t\treturn 1;\n" +
                "\t\t\t}\n" +
                "\t\t}\n" +
                "\t\treturn 0;\n" +
                "\t}\n");
        sb.append("}\n");
        FileUtil.writeString(sb.toString(), "FileSignatureUtil.java", StandardCharsets.UTF_8);
    }
}
